"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 硬件故障类--CPU
Case Name   : TPCC背景业务下，构造cpu占用100%故障，重启数据库
Create At   : 2020-10-27
Owner       : n@ningyali
Description :
    1、利用benchmarksql工具运行TPCC
    2、利用cfe工具构造cpu压力100%
    ./cfe "inject rCPU_Overloadal (cpuid1, cpuid2, usage) values({}, {}, 100)"
    3、重启数据库
    gs_om -t stop && gs_om -t start
    4、检查集群状态
    gs_om -t status --detail
    5、消除cpu压力故障
Expect      :
    1、TPCC运行正常
    2、故障注入成功
    3、TPCC运行正常
    4、数据库重启成功
    5、数据库集群装态正常
    6、消除恢复成功
History     :
    2021/1/20 n@ningyali tpcc线程设置最大等待时间
"""

import unittest
import time

from yat.test import Node
from yat.test import macro

from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger


class CPUOverloadAndRunTPCC(unittest.TestCase):
    primary_sh = CommonSH('PrimaryDbUser')
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.log = Logger()
        self.log.info(
            '---------Opengauss_Reliability_Hardware_Case001:开始执行---------')
        self.primary_root_node = Node(node='PrimaryRoot')
        self.primary_user_node = Node(node='PrimaryDbUser')
        self.com = Common()
        self.Constant = Constant()

    def test_main(self):
        self.log.info("---------------开启TPCC----------------")
        tpcc_thread = ComThread(self.com.startTPCC,
                                args=(self.primary_root_node,
                                      macro.TPCC_PATH,))
        tpcc_thread.setDaemon(True)
        tpcc_thread.start()

        time.sleep(10)

        self.log.info("---------------获取cpu个数----------------")
        shell_cmd = "cat /proc/cpuinfo |grep 'processor'|wc -l"
        self.log.info(shell_cmd)
        cpu_num = self.primary_root_node.sh(shell_cmd).result()
        self.log.info(cpu_num)

        self.log.info("---------------利用cfe工具构造cpu压力100%----------------")
        # 因执行该指令后不会退出，所以使用启线程的方式，在主线程结束后会退出该子线程
        inject_command = f"rCPU_Overloadal (cpuid1, cpuid2, usage) " \
            f"values(0, {int(cpu_num) - 1}, 100)"
        inject_thread = ComThread(self.com.cfe_inject,
                                  args=(self.primary_root_node,
                                        inject_command,))
        inject_thread.start()

        time.sleep(10)

        self.log.info("---------------获取cfe注入故障结果----------------")
        inject_result = inject_thread.get_result()
        self.log.info(inject_result)

        self.log.info("---------------TPCC运行正常----------------")
        tpcc_thread.join(60 * 10)
        tpcc_result = tpcc_thread.get_result()
        self.log.info(tpcc_result)
        if tpcc_result is not None:
            self.assertNotIn(self.Constant.TPCC_ERROR, tpcc_result)

        self.log.info("-------------重启数据库---------------")
        is_stopped = self.primary_sh.stopDbCluster()
        self.assertTrue(is_stopped)
        start_msg = self.primary_sh.startDbCluster(True)
        self.log.info(start_msg)

        self.log.info("---------------检查集群状态----------------")
        db_status = self.primary_sh.getDbClusterStatus()
        self.assertTrue("Degraded" in db_status or "Normal" in db_status)

    def tearDown(self):
        self.log.info("-------------消除cpu压力故障---------------")
        clean_command = f"rCPU_Overloadal"
        clean_thread = ComThread(self.com.cfe_clean,
                                 args=(self.primary_root_node,
                                       clean_command,))
        clean_thread.start()
        self.log.info(
            '--------Opengauss_Reliability_Hardware_Case001:执行完成--------')
